

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" type="image/png" href="/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="CodeHope">
  <meta name="author" content="CodeHope">
  <meta name="keywords" content="希望">
  <title>Java中的String类 - CodeHope</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      
        
          
          
          
        
        <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.22.0/themes/prism-tomorrow.min.css" />
      
      
        <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.22.0/plugins/line-numbers/prism-line-numbers.min.css" />
      
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"quancundexiwang.wang","root":"/","version":"1.8.7","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":true,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"onlypost":true},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":"Mi65hxq7VAFUDwOLeIGAOgiV-gzGzoHsz","app_key":"hMuhiD4FRqhns4giqLiEH9HG","server_url":null}}};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.3.0"></head>


<body>
  <header style="height: 80vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>CodeHope</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                村头
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                我
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('http://qiniuyun.quancundexiwang.wang/20210209215502.png') repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="Java中的String类">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-02-09 21:49" pubdate>
        2021年2月9日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.7k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      46
       分钟
    </span>
  

  
  
</div>

            
          </div>

          
            <div class="scroll-down-bar">
              <i class="iconfont icon-arrowdown"></i>
            </div>
          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Java中的String类</h1>
            
            <div class="markdown-body">
              <h1 id="Java中的String类"><a href="#Java中的String类" class="headerlink" title="Java中的String类"></a>Java中的<code>String</code>类</h1><h2 id="从源码分析类属性和方法"><a href="#从源码分析类属性和方法" class="headerlink" title="从源码分析类属性和方法"></a>从源码分析类属性和方法</h2><p>首先我们回顾一下，常见的几种创建字符串的方式</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"哈哈哈"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> s2 <span class="token operator">=</span> <span class="token string">"呼呼呼呼"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//空字符串</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<blockquote>
<p>想要了解一个类，最好的办法就是看这个类的实现源代码，来看一下String类的源码：</p>
</blockquote>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">//String类是final类，也即意味着String类不能被继承，并且它的成员方法都默认为final方法</span>
<span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">String</span>
    <span class="token keyword">implements</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span><span class="token punctuation">,</span> <span class="token class-name">Comparable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span><span class="token punctuation">,</span> <span class="token class-name">CharSequence</span>
<span class="token punctuation">&#123;</span>
  	<span class="token comment">//列举出了String类中所有的成员属性</span>
    <span class="token comment">/** 
    The value is used for character storage.
    String类其实是通过char数组来保存字符串的。
    */</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">char</span> value<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token comment">/** The offset is the first index of the storage that is used. */</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">int</span> offset<span class="token punctuation">;</span>

    <span class="token comment">/** The count is the number of characters in the String. */</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">int</span> count<span class="token punctuation">;</span>

    <span class="token comment">/** Cache the hash code for the string */</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> hash<span class="token punctuation">;</span> <span class="token comment">// Default to 0</span>

    <span class="token comment">/** use serialVersionUID from JDK 1.0.2 for interoperability */</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> serialVersionUID <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">6849794470754667710L</span><span class="token punctuation">;</span>

    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>从上面可以看出几点：</p>
<ul>
<li><p><span><code>String</code>类是<code>final</code>类，也即意味着<code>String</code><strong>类不能被继承</strong>，并且它的成员方法都默认为<code>final</code>方法。</span>(在Java中，被final修饰的类是不允许被继承的，并且该类中的成员方法都默认为<code>final</code>方法。)</p>
<p><span style='color:red'><strong>(问题来了：为什么是final的?)</strong></span></p>
<p><strong>安全性</strong> ：这种类是非常底层的，和操作系统的接触是非常频繁的，如果可以被继承，那么一些人重写了一些方法，往操作系统内部写入一段具有恶意攻击性质的代码什么的，这不就成了核心病毒了么？</p>
<p><strong>效率：</strong>设计成final，JVM才不用对相关方法在虚函数表中查询，而直接定位到String类的相关方法上，提高了执行效率。</p>
</li>
<li><p>String类其实是通过char数组来保存字符串的。</p>
</li>
</ul>
<p>下面再继续看String类的一些方法实现：</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">substring</span><span class="token punctuation">(</span><span class="token keyword">int</span> beginIndex<span class="token punctuation">,</span> <span class="token keyword">int</span> endIndex<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>beginIndex <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">StringIndexOutOfBoundsException</span><span class="token punctuation">(</span>beginIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>endIndex <span class="token operator">></span> count<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">StringIndexOutOfBoundsException</span><span class="token punctuation">(</span>endIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>beginIndex <span class="token operator">></span> endIndex<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">StringIndexOutOfBoundsException</span><span class="token punctuation">(</span>endIndex <span class="token operator">-</span> beginIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
  	<span class="token comment">// 如果传入的不会对原string产生影响，就返回原本的字符串</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>beginIndex <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>endIndex <span class="token operator">==</span> count<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token keyword">this</span> <span class="token operator">:</span>
  	<span class="token comment">//否则就返回一个新的字符串对象</span>
        <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span>offset <span class="token operator">+</span> beginIndex<span class="token punctuation">,</span> endIndex <span class="token operator">-</span> beginIndex<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">concat</span><span class="token punctuation">(</span><span class="token class-name">String</span> str<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">int</span> otherLen <span class="token operator">=</span> str<span class="token punctuation">.</span><span class="token function">length</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>otherLen <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">char</span> buf<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">char</span><span class="token punctuation">[</span>count <span class="token operator">+</span> otherLen<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token function">getChars</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> count<span class="token punctuation">,</span> buf<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    str<span class="token punctuation">.</span><span class="token function">getChars</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> otherLen<span class="token punctuation">,</span> buf<span class="token punctuation">,</span> count<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> count <span class="token operator">+</span> otherLen<span class="token punctuation">,</span> buf<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//返回新的字符串对象</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">replace</span><span class="token punctuation">(</span><span class="token keyword">char</span> oldChar<span class="token punctuation">,</span> <span class="token keyword">char</span> newChar<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>oldChar <span class="token operator">!=</span> newChar<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">int</span> len <span class="token operator">=</span> count<span class="token punctuation">;</span>
        <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
        <span class="token keyword">char</span><span class="token punctuation">[</span><span class="token punctuation">]</span> val <span class="token operator">=</span> value<span class="token punctuation">;</span> <span class="token comment">/* avoid getfield opcode */</span>
        <span class="token keyword">int</span> off <span class="token operator">=</span> offset<span class="token punctuation">;</span>   <span class="token comment">/* avoid getfield opcode */</span>

        <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">++</span>i <span class="token operator">&lt;</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>val<span class="token punctuation">[</span>off <span class="token operator">+</span> i<span class="token punctuation">]</span> <span class="token operator">==</span> oldChar<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">break</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">char</span> buf<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">char</span><span class="token punctuation">[</span>len<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> j <span class="token operator">&lt;</span> i <span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            buf<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> val<span class="token punctuation">[</span>off<span class="token operator">+</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">while</span> <span class="token punctuation">(</span>i <span class="token operator">&lt;</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
            <span class="token keyword">char</span> c <span class="token operator">=</span> val<span class="token punctuation">[</span>off <span class="token operator">+</span> i<span class="token punctuation">]</span><span class="token punctuation">;</span>
            buf<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span>c <span class="token operator">==</span> oldChar<span class="token punctuation">)</span> <span class="token operator">?</span> newChar <span class="token operator">:</span> c<span class="token punctuation">;</span>
            i<span class="token operator">++</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> len<span class="token punctuation">,</span> buf<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//返回新的字符串对象</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<blockquote>
<p>从上面的三个方法可以看出，无论是sub、concat还是replace操作都不是在原有的字符串上进行的，而是重新生成了一个新的字符串对象。也就是说进行这些操作后，最原始的字符串并没有被改变。(sub如果么有变的话，就不会生成新的)</p>
</blockquote>
<blockquote>
<p><span style='color:red'>在这里要永远记住一点：“String对象一旦被创建就是固定不变的了，对String对象的任何改变都不影响到原对象，相关的任何change操作都会生成新的对象”。</span></p>
</blockquote>
<h2 id="String对象的常量池（重要）"><a href="#String对象的常量池（重要）" class="headerlink" title="String对象的常量池（重要）"></a>String对象的常量池（重要）</h2><p>和之前总结包装类看到<code>Integer</code>类一样，<code>String类</code> 也是有自己的常量池，用来缓存被创建的的字符串对象，然后程序运行需要的字符串对象，会优先在常量池中查询，查到了就直接引用查到的对象实例，否则就去新<code>new </code>一个新的字符串对象，当然也会被放入常量池中。</p>
<blockquote>
<p>符串的分配和其他对象分配一样，是需要消耗高昂的时间和空间的，而且字符串我们使用的非常多。JVM为了提高性能和减少内存的开销，在实例化字符串的时候进行了一些优化：</p>
<p>使用字符串常量池。每当我们创建字符串常量时，JVM会首先检查字符串常量池，如果该字符串已经存在常量池中，那么就直接返回常量池中的实例引用。如果字符串不存在常量池中，就会实例化该字符串并且将其放到常量池中。</p>
</blockquote>
<p>我们来从实际的例子中看一看String 的各种情况,来看下面的程序</p>
<p>1**.编译器确定**</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token comment">//1.编译器确定</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">test1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token class-name">String</span> str1<span class="token operator">=</span><span class="token string">"hello"</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> str2<span class="token operator">=</span><span class="token string">"hello"</span><span class="token punctuation">;</span>
    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1<span class="token operator">==</span>str2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true 可以看出str1跟str2是指向同一个对象 </span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>我们来看一看内部操作的过程：</p>
<blockquote>
<p>当执行<code>String str1=&quot;aaa&quot;</code>时，JVM首先会去字符串常量池中查找是否存在<code>&quot;aaa&quot;</code>这个对象，不存在，则在字符串池中创建<code>&quot;aaa&quot;</code>这个对象，然后将池中<code>&quot;aaa&quot;</code>这个对象的引用地址返回给字符串常量<code>str1</code>，这样<code>str1</code>会指向池中<code>&quot;aaa&quot;</code>这个字符串对象；</p>
<p>当创建字符串对象str2时，字符串池中已经存在”aaa”这个对象，直接把对象”aaa”的引用地址返回给str2，这样str2指向了池中”aaa”这个对象</p>
</blockquote>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209153537.png" srcset="/img/loading.gif" alt="image-20210209153536645"></p>
<p>很明显，<code>str1</code>、<code>str2</code>都是指向JVM字符串常量池中的<code>&quot;hello&quot;</code>对象，他们指向同一个对象。而且是在编译器就确定了。</p>
<p>所以<code>str1==str2 为true</code></p>
<p>结合上面例子，总结如下:单独使用<code>&quot;xx&quot;</code>引号创建的字符串都是常量,编译期就已经确定存储到String Pool中。</p>
<p>但是如果此时我们使用<code>new</code>关键字生成了一个新的字符串对象 <code>str3</code></p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> str3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div>
<p>在执行**<code>String str3 = new String(&quot;hello&quot;)</code>**的时候：</p>
<p>首先走常量池的路线取到一个实例的引用,也就是先去查常量池中有没有这个字符串。</p>
<p><span style='background:#e8e837;color:#323232'>如果有，则不在池中再去创建<code>&quot;hello&quot;</code>这个对象了,直接在堆中创建一个<code>&quot;hello&quot;</code>字符串对象，然后将堆中的这个<code>&quot;hello&quot;</code>对象的地址返回赋给栈中新生的引用<code>str3</code>，这样，<code>str3</code>就指向了堆中创建的这个<code>&quot;hello&quot;</code>字符串对象。</span></p>
<p><span style='background:#e8e837;color:#323232'>如果没有，则首先在字符串池中创建一个”hello”字符串对象，然后再在堆中创建一个<code>&quot;hello&quot;</code>字符串对象，然后将堆中这个”hello”字符串对象的地址返回赋给<code>str3</code>引用，这样，<code>str3</code>指向了堆中创建的这个<code>&quot;hello&quot;</code>字符串对象。</span></p>
<p>但是在Java中根本就不存在两个完全一模一样的字符串对象。故堆中的”hello”应该是引用字符串常量池中”hello”.</p>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209170928.png" srcset="/img/loading.gif" alt="image-20210209170927445"></p>
<p>通过<code>hashCode</code>验证究竟是不是使用的同一个字符串</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//99162322</span>

<span class="token class-name">String</span> s2 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s2<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//99162322</span>

<span class="token class-name">String</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s3<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//99162322</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>可以看到只要是同一个字符串，不论怎样创建<code>hashCode都是相同的</code></p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s1 <span class="token operator">==</span> s3<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div>
<p><span style='color:red'>那么为什么<code>str3</code>为什么和<code>str2</code>或者<code>str1</code>仍然不相同呢？</span></p>
<p>因为<code>str3</code>存的是字符串对象在堆区域中的引用地址啊！</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> str3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str3 <span class="token operator">==</span> str4<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>

<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str3<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//99162322</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str4<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//99162322</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>在这里比较的 <code>str3</code> 和 <code>str4</code> ,比较的实际是堆中的对象的引用地址,但是指向的都是常量池中唯一的字符串，所以<code>hashCode</code>仍然是相同的。</p>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209173725.png" srcset="/img/loading.gif" alt="image-20210209173723858"></p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">"he"</span><span class="token operator">+</span> <span class="token string">"llo"</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1<span class="token operator">==</span>str2<span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>当一个字符串由多个字符串常量连接而成时，它自己肯定也是字符串常量，所以str2也同样在编译期就被解析为一个字符串常量，</p>
<p>我们也可以去看这个编译后的class文件:</p>
<p><code>App.class</code></p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>也同样在编译期就被解析为一个字符串常量，所以str2也是常量池中”hello”的一个引用</p>
<p>所以<code>str1 == str2</code>为<code>true</code>.</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">"helloWorld"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">"hello"</span> <span class="token operator">+</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"World"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>用new String() 创建的字符串不是常量，不能在编译期就确定，所以new String() 创建的字符串不放入常量池中，它们有自己的地址空间。</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">"abc"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">"def"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str3 <span class="token operator">=</span> str1 <span class="token operator">+</span> str2<span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p><code>String str1 = &quot;abc&quot;;String str2 = &quot;def&quot;;</code> 这两个会在常量池中创建两个字符串，而<code>String str3=str1+str2</code>是在运行时刻才能知道的,new对象也是在运行时才做的,这段代码总共创建了5个对象，字符串池中两个、堆中三个.</p>
<p><code>+</code>运算符会在<code>堆中建立来两个String对象</code>，这两个对象的值分别是<code>&quot;abc&quot;和&quot;def&quot;</code>，也就是说从字符串池中复制这两个值，然后在堆中创建两个对象，然后再建立对象str3,然后将”abcdef”的堆地址赋给str3。</p>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209181452.png" srcset="/img/loading.gif" alt="image-20210209181451423"></p>
<p>所以:</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str3 <span class="token operator">==</span> <span class="token string">"abcdef"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div>
<blockquote>
<p>字符串池的优缺点：</p>
<p>字符串池的优点就是避免了相同内容的字符串的创建，节省了内存，省去了创建相同字符串的时间，同时提升了性能；另一方面，字符串池的缺点就是牺牲了JVM在常量池中遍历对象所需要的时间，不过其时间成本相比而言比较低。</p>
</blockquote>
<h2 id="关于String-intern-（待补充）"><a href="#关于String-intern-（待补充）" class="headerlink" title="关于String.intern() （待补充）"></a>关于<code>String.intern()</code> （待补充）</h2><h2 id="和-equlas方法的区别"><a href="#和-equlas方法的区别" class="headerlink" title="==和 equlas方法的区别"></a><code>==</code>和 <code>equlas</code>方法的区别</h2><blockquote>
<p><code>==</code>一般用来比较两个基本数据类型变量（局部变量）的值是否相等</p>
</blockquote>
<blockquote>
<p>如果用于比较引用<strong>数据类型的变量</strong>，也是比较变量的值，不同的是，引用数据类型变量存储的是数据的首地址(即数据在堆中存放的地址)，所以是<code>地址的比较</code>。</p>
</blockquote>
<p><strong>Java中的8种基本数据类型：</strong></p>
<ul>
<li><p>整型4种：byte(1字节),short(2字节),int(4字节),long(8字节)</p>
</li>
<li><p>浮点型2种：float(4字节),double(8字节)</p>
</li>
<li><p>字符型1种：char(2字节)</p>
</li>
<li><p>布尔型1种：boolean(1bit)</p>
</li>
</ul>
<p><strong>Java中的引用数据类型：</strong></p>
<ul>
<li>类（包含String）</li>
<li>接口</li>
<li>数组</li>
</ul>
<blockquote>
<p><code>equals()</code>方法一般用于两个对象的内容是否相等。内容即变量所存储的地址指向的数据，在堆中。</p>
</blockquote>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token string">"123"</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> s2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"123"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s1 <span class="token operator">==</span> s2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209202535.png" srcset="/img/loading.gif" alt="image-20210209202535057"></p>
<p><code>equals()</code> 比较的是最终指向的值，<code>==</code>比较的是变量的引用地址</p>
<h2 id="String的不可变性！✨"><a href="#String的不可变性！✨" class="headerlink" title="String的不可变性！✨"></a><code>String</code>的不可变性！✨</h2><blockquote>
<p>String 被声明为 final，是不可变的，它也不可被继承。</p>
</blockquote>
<blockquote>
<p><code>String</code>对象，一旦被创建，则不能修改，是不可变的，所谓的修改其实是创建了新的对象，如果改变字符串内容，那么就会指向新的内存区域。</p>
</blockquote>
<p>在 Java 8 中，String 是使用 char 数组实现的。</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">String</span> <span class="token keyword">implements</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span><span class="token punctuation">,</span> <span class="token class-name">Comparable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span><span class="token punctuation">,</span> <span class="token class-name">CharSequence</span> <span class="token punctuation">&#123;</span> 
   <span class="token comment">/** The value is used for character storage. */</span> 
   <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">char</span> value<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

   <span class="token comment">/** Cache the hash code for the string */</span> 
   <span class="token keyword">private</span> <span class="token keyword">int</span> hash<span class="token punctuation">;</span> <span class="token comment">// Default to 0</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p> 到了 Java 9 ，String 类的实现改用 byte 数组实现，同时使用 coder 来标识使用了哪种编码。</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">String</span>
    <span class="token keyword">implements</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span><span class="token punctuation">,</span> <span class="token class-name">Comparable</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">></span></span><span class="token punctuation">,</span> <span class="token class-name">CharSequence</span><span class="token punctuation">,</span>
               <span class="token class-name">Constable</span><span class="token punctuation">,</span> <span class="token class-name">ConstantDesc</span> <span class="token punctuation">&#123;</span>

    <span class="token comment">/**
     * The value is used for character storage.
     * 该值用于字符存储
     */</span>
    <span class="token annotation punctuation">@Stable</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> value<span class="token punctuation">;</span>

    <span class="token comment">/**
     * The identifier of the encoding used to encode the bytes in
     * &#123;@code value&#125;. 用于对字节进行编码的编码的标识符
     */</span>
    <span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">byte</span> coder<span class="token punctuation">;</span>

    <span class="token comment">/** Cache the hash code for the string 
    *		缓存字符串的哈希码
    */</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> hash<span class="token punctuation">;</span> <span class="token comment">// Default to 0</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<blockquote>
<p>value 数组被声明为 final，并且 String 内部也没有改变 value 数组的方法，可以去看他的源码，大部分的字符串操作都是去<code>new</code>了一个新的字符串对象,不会去改变原有的字符串,因此 String 是不可变的。比如这个<code>substring</code>方法,</p>
</blockquote>
<div class="code-wrapper"><pre class="line-numbers language-none"><code class="language-none">public String substring(int beginIndex, int endIndex) &#123;
    int length &#x3D; length();
    checkBoundsBeginEnd(beginIndex, endIndex, length);
    int subLen &#x3D; endIndex - beginIndex;
    if (beginIndex &#x3D;&#x3D; 0 &amp;&amp; endIndex &#x3D;&#x3D; length) &#123;
        return this;
    &#125;
    return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
                      : StringUTF16.newString(value, beginIndex, subLen);
&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>他的返回值都是执行了一个<code>newString</code>的方法,而这个<code>newString</code>本质就是去新建了一个字符串的对象。</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">String</span> <span class="token function">newString</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> val<span class="token punctuation">,</span> <span class="token keyword">int</span> index<span class="token punctuation">,</span> <span class="token keyword">int</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">copyOfRange</span><span class="token punctuation">(</span>val<span class="token punctuation">,</span> index<span class="token punctuation">,</span> index <span class="token operator">+</span> len<span class="token punctuation">)</span><span class="token punctuation">,</span>LATIN1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>我们看一下，下面这个代码在虚拟机内存中发生了什么</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token string">"helloWorld"</span><span class="token punctuation">;</span>
s1 <span class="token operator">=</span> s1 <span class="token operator">+</span> <span class="token string">"HelloJava"</span><span class="token punctuation">;</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>1.首先去常量池查找 <code>&quot;helloWorld&quot;</code>是否存在，不存在则在常量池中新建一个<code>&quot;helloWorld&quot;</code>字符串</p>
<p>2.当执行<code>s1 + &quot;HelloJava&quot;;</code>那么作为常量池中引用的字符串的常量值<code>helloWorld</code>，就会和<code>HelloJava</code>,拼接成新的字符串，放入常量池中，然后赋值给<code>s1</code></p>
<p><img src="http://qiniuyun.quancundexiwang.wang/20210209211339.gif" srcset="/img/loading.gif" alt="Feb-09-2021 21-12-32"></p>
<p><strong>不可变的优势</strong></p>
<ul>
<li><p>线程安全<br>因为 <code>String</code> 的不可变性，所以在多线程的环境下，可以被安全使用。</p>
</li>
<li><p><code>hash</code> 值不需要重复计算<br>一个 <code>String</code> 被创建后，那么它的 <code>hash</code> 值只需要计算一次；<br>比如使用 <code>String </code>做为 <code>HashMap</code> 中的 <code>key</code> ，那么不需要重复计算 <code>hash</code> 值。</p>
</li>
<li><p><code>String Pool</code><br>一个 String 被创建后，被可以放入 String Pool 中，就可以被其他地方所引用；因为 String 是不可变的，所以才能实现 String Pool </p>
</li>
</ul>
<p><strong>不可变的缺点</strong></p>
<blockquote>
<p> 当需要频繁操作字符串的时候，会在常量池中产生很多中间变量。又因为每次创建字符串都要去遍历常量池，当常量池中的临时变量过多常量池的遍历效率就会降低，所以当频繁操作字符串的时候，我们可以使用下面要介绍的<code>StringBuilder</code>/<code>StringBuffer</code>.</p>
</blockquote>
<h2 id="StringBuilder-StringBuffer"><a href="#StringBuilder-StringBuffer" class="headerlink" title="StringBuilder/StringBuffer"></a><code>StringBuilder</code>/<code>StringBuffer</code></h2><p><code>StringBuilder</code>和<code>String</code>的不同</p>
<blockquote>
<p><code>String</code>具有不可变性质，而<code>StringBuilder</code>/<code>StringBuffer</code>不具有这个特性。</p>
</blockquote>
<p><code>StringBuilder</code>/<code>StringBuffer</code> 之间的区别： </p>
<p><code>StringBuilder</code>是线程不安全的，它的执行效率比```StriingBuffer``要高</p>
<p><code>StringBuffer</code>是线程安全的，它的执行效率比<code>StringBuilder</code>要低</p>
<p><span style='color:red'><strong>总结一下</strong></span><br><code>String</code>：适用于少量的字符串操作的情况</p>
<p><code>StringBuilder</code>：适用于单线程下在字符缓冲区进行大量操作的情况</p>
<p><code>StringBuffer</code>：适用多线程下在字符缓冲区进行大量操作的情况</p>
<p>实例使用</p>
<div class="code-wrapper"><pre class="line-numbers language-java" data-language="java"><code class="language-java"><span class="token class-name">StringBuilder</span> str1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//hello</span>

<span class="token class-name">StringBuilder</span> str2 <span class="token operator">=</span> str1<span class="token punctuation">;</span>

str2<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">","</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"Java"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 

<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//hello,Java</span>
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//hello,Java</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>就可以发现，StringBuilder类的成员方法操作都是一块内存空间。</p>
<p><a target="_blank" rel="noopener" href="https://www.matools.com/api/java8">更多请参考文档</a></p>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/Java/">Java</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Java%E5%9F%BA%E7%A1%80%E5%AD%A6%E4%B9%A0/">Java基础学习</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/posts/46616/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">计算机中的进制</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/posts/48024/">
                        <span class="hidden-mobile">Java中的包装类</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments">
                
                
  <div id="vcomments"></div>
  <script type="text/javascript">
    Fluid.utils.waitElementVisible('vcomments', function() {
      Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js', function () {
        new Valine({
          el: "#vcomments",
          app_id: "Mi65hxq7VAFUDwOLeIGAOgiV-gzGzoHsz",
          app_key: "hMuhiD4FRqhns4giqLiEH9HG",
          placeholder: "说点什么",
          path: window.location.pathname,
          avatar: "retro",
          meta: ["nick","mail","link"],
          pageSize: "10",
          lang: "zh-CN",
          highlight: false,
          recordIP: false,
          serverURLs: "",
        });
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the
    <a target="_blank" href="https://valine.js.org" rel="nofollow noopener noopener">comments powered by Valine.</a>
  </noscript>


              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
    

  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  
  <!-- 备案信息 -->
  <div class="beian">
    <span>
      <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
        豫ICP备20009912号-1
      </a>
    </span>
    
  </div>


  
</footer>

<!-- SCRIPTS -->

  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":true,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    
      <script  src="/js/lazyload.js" ></script>
    
  



  
    
  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.0/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.0/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.11/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    (function () {
      var path = "http://qiniuyun.quancundexiwang.wang/xmlSearch.xml";
      var inputArea = document.querySelector("#local-search-input");
      inputArea.onclick = function () {
        searchFunc(path, 'local-search-input', 'local-search-result');
        this.onclick = null
      }
    })()
  </script>















<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>



</body>
</html>
